package com.dyb.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class NettyEchoServer {

    private int port;

    public NettyEchoServer(int port) {
        this.port = port;
    }

    ServerBootstrap sb = new ServerBootstrap();

    public static void main(String[] args) {

        NettyEchoServer nettyEchoServer = new NettyEchoServer(8888);
        nettyEchoServer.startServer();
    }

    public void startServer () {

        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();
        try {
            // 1.设置反应器线程组
            sb.group(boss, worker);
            // 2.设置通道类型
            sb.channel(NioServerSocketChannel.class);
            // 3.设置监听端口
            sb.localAddress(port);
            // 4.设置通道参数 ps:option主要是针对boss线程组，child主要是针对worker线程组
            sb.option(ChannelOption.SO_KEEPALIVE, true);
            sb.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
            sb.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
            // 5.设置通道流水线
            sb.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) {
                    ch.pipeline().addLast(EchoServerHandler.INSTANCE);
                }
            });

            ChannelFuture future = sb.bind();
            future.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (future.isSuccess()) {
                        System.out.println("服务端启动成功");
                    } else {
                        System.out.println("服务端启动失败");
                    }
                }
            });

            future.sync();
            ChannelFuture channelFuture = future.channel().closeFuture();
            channelFuture.sync();
        }catch (Exception e) {
            e.printStackTrace();
        } finally {
            worker.shutdownGracefully();
            boss.shutdownGracefully();
        }
    }
}

/**
 * Sharable共享类型的业务处理器
 * @author dyb
 * @date 2020/7/24
 */
@ChannelHandler.Sharable
class EchoServerHandler extends ChannelInboundHandlerAdapter {
    // 没有共享资源可以使用在Channel中共享
    public static final EchoServerHandler INSTANCE = new EchoServerHandler();

    private EchoServerHandler() {
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        int length = byteBuf.readableBytes();
        byte[] arr = new byte[length];
        // 将byteBuf读取到arr
        // 不会改变读指针位置
        byteBuf.getBytes(0, arr);

        // 保证byteBuf读执行为0
        // byteBuf.markReaderIndex();
        // 会改变读指针位置，造成客户端接收不到消息
        // byteBuf.readBytes(arr);
        // byteBuf.resetReaderIndex();

        System.out.println("服务端接收数据=>"+ new String(arr, "utf-8"));

        // byteBuf出站后自动释放
        ChannelFuture future = ctx.writeAndFlush(byteBuf);
        future.sync();
        System.out.println("buf引用" + byteBuf.refCnt());

//        ctx.fireChannelRead(msg);
    }
}